package com.online.onlinestudent.util;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 三段：
 * 1、Header（头部）：
 * {
 *     "alg": "HS256",  // 编码算法--->可逆的加密算法
 *     "typ": "JWT"    // 令牌类型
 * }
 * 2、Payload（负载）：
 * {
 *     "sub": "admin",  // 主题 --> 放一些用户信息在里面
 *     "exp": 1516239022,  // 过期时间  --> 时间戳（要过期的那个时间点的时间戳）
 *     "iat": 1516238962  // 颁发时间
 *       // 其他自定义字段
 * }
 * 3、Signature（签名）：
 * 将Header和Payload进行Base64编码，然后使用秘钥（secret）进行加密，生成签名。--->不可逆的加密算法，只有服务器知道秘钥才能解密。
 *
 */
@Component
public class JwtUtil {

    @Autowired
    private TokenProperties properties;

    /**
     * eyJhbGciOiJIUzI1NiJ9.
     * eyJuYW1lIjoi5byg5LiJIiwiaWQiOiIxMDAxIiwiYWdlIjoyMCwiZXhwIjoxNzI0ODI5NjMwfQ.
     * 77sN9Fpfn-czl6kNmyeC9AGoea0bipRQSIJ3BPUWP3U
     */


    /**
     * 生成token
     * @param subject
     * @return
     */
    public String generateToken(Map<String, Object> subject) {
        long l = System.currentTimeMillis();
        Date date = new Date(l + properties.getExpire());
        JwtBuilder jwtBuilder = Jwts.builder().setClaims(subject)
                .setExpiration(date)
                .signWith(SignatureAlgorithm.HS256, properties.getSecret());
        return jwtBuilder.compact();//生成token
    }

    /**
     * 用来解析token
     * @param token
     * @return
     */
    public boolean verifyToken(String token) {
        // 如果解析的过程中发现token被篡改过，那么就会报异常，如果发现已经过期，也会报异常
        try {
            Jwts.parser().setSigningKey(properties.getSecret()).parseClaimsJws(token);
        } catch (Exception e) {//只要发生异常，我们就认为token验证失败
            return false;
        }
        return true;
    }

    /**
     * 获取主题
     * @param token
     * @return
     */
    public Map<String, Object> getSubject(String token) {
        Claims claims = Jwts.parser().setSigningKey(properties.getSecret()).parseClaimsJws(token).getBody();
        Map<String, Object> map = new HashMap<>();
        for (String key : claims.keySet()) {
            map.put(key, claims.get(key));
        }
        return map;
    }

    /**
     * 获取用户id
     * @param token
     * @return
     */
    public long getUserId(String token) {
        Map<String, Object> subject = getSubject(token);
        return Long.parseLong(subject.get(properties.getPrefixKey()).toString());
    }

    /**
     * 获取用户id
     * @return
     */
    public long getUserId() {
        ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = sra.getRequest();
        String token = request.getHeader(properties.getPrefixKey());
        return getUserId(token);
    }
}
